package com.company.cloud.tenant.modules.mgr.service.impl;

import cn.hutool.core.lang.Dict;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.company.cloud.common.asserts.ValidatorUtils;
import com.company.cloud.common.bean.BaseClientResult;
import com.company.cloud.common.bean.LoginSimpleUserInfo;
import com.company.cloud.common.constant.BaseConstant;
import com.company.cloud.common.constant.BaseReturnEnum;
import com.company.cloud.common.exception.BusinessException;
import com.company.cloud.common.utils.CheckUtils;
import com.company.cloud.common.utils.LocalDateTimeUtils;
import com.company.cloud.common.utils.StrSplitUtils;
import com.company.cloud.tenant.constant.ErrorTenantEnum;
import com.company.cloud.tenant.constant.TenantConstant;
import com.company.cloud.tenant.modules.api.request.*;
import com.company.cloud.tenant.modules.api.response.TenantFull;
import com.company.cloud.tenant.modules.base.entity.TenantApplicationInfo;
import com.company.cloud.tenant.modules.base.entity.TenantInfo;
import com.company.cloud.tenant.modules.base.service.TenantApplicationInfoService;
import com.company.cloud.tenant.modules.base.service.TenantInfoService;
import com.company.cloud.tenant.modules.cache.utils.TenantConvertUtils;
import com.company.cloud.tenant.modules.cache.utils.TenantIdUtils;
import com.company.cloud.tenant.modules.mgr.service.TenantMgrService;
import com.company.cloud.user.modules.api.request.RegisterEmployeeRequest;
import com.company.cloud.user.modules.api.request.ValidateUserRequest;
import com.company.cloud.user.modules.api.response.UserFull;
import com.company.cloud.user.modules.api.response.UserSimple;
import com.company.cloud.user.modules.api.response.ValidateUserResponse;
import com.company.cloud.user.modules.api.service.UserRegisterRemoteService;
import com.company.cloud.user.modules.api.service.UserRemoteService;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;

@Service
public class TenantMgrServiceImpl implements TenantMgrService {
    @Autowired
    private TenantInfoService tenantInfoService;
    @Autowired
    private TenantApplicationInfoService tenantApplicationInfoService;
    @Autowired
    @Qualifier("userRegisterRemoteServiceImpl")
    private UserRegisterRemoteService userRegisterRemoteService;
    @Autowired
    @Qualifier("userRemoteServiceImpl")
    private UserRemoteService userRemoteService;

    @Override
    public IPage<TenantFull> query(TenantQueryRequest request) {
        IPage<TenantInfo> page =  tenantInfoService.page(
                new Page<TenantInfo>(request.getPage(), request.getRows()),
                new QueryWrapper<TenantInfo>()
                        .eq("rows_state", BaseConstant.EnabledEnum.ENABLED.getCode())
                        .eq(StringUtils.hasText(request.getTenantCode()), "tenant_code", request.getTenantCode())
                        .eq(StringUtils.hasText(request.getName()), "name", request.getName())
                        .eq(StringUtils.hasText(request.getType()), "type", request.getType())
                        .eq(StringUtils.hasText(request.getSourceType()), "source_type", request.getSourceType())
                        .eq(StringUtils.hasText(request.getSource()), "source", request.getSource())
                        .eq(StringUtils.hasText(request.getState()), "state", request.getState())
        );

        Set<Integer> userIds=new HashSet<>();
        if(!CollectionUtils.isEmpty(page.getRecords())){
            page.getRecords().forEach(item->{
                if(CheckUtils.hasInt(item.getAdminUserId())){
                    userIds.add(item.getAdminUserId());
                }
            });
        }
        BaseClientResult<Map<Integer, UserSimple>> userSimpleResult = userRemoteService.getUserMapByIds(userIds);
        Map<Integer, UserSimple> userSimpleMap = BaseClientResult.getResultData(userSimpleResult,new HashMap<Integer, UserSimple>());
        IPage<TenantFull> data=page.convert(new Function<TenantInfo, TenantFull>() {
            @Override
            public TenantFull apply(TenantInfo entity) {
                return TenantConvertUtils.getTenantFull(entity,userSimpleMap);
            }
        });
        return data;
    }


    private Dict getSaveMap(TenantAddRequest params, LoginSimpleUserInfo userInfo) {
        TenantInfo entity=new TenantInfo();
        if(StringUtils.isEmpty(params.getTenantCode())){
            entity.setTenantCode(TenantIdUtils.getTenantId());
        }else{
            entity.setTenantCode(params.getTenantCode());
        }
        entity.setName(params.getName());
        entity.setShortName(params.getShortName());
        entity.setType(params.getType());
        entity.setLogo(params.getLogo());
        entity.setSourceType(params.getSourceType());
        entity.setSource(params.getSource());

        entity.setLinkManName(params.getLinkManName());
        entity.setLinkManMobile(params.getLinkManMobile());
        entity.setLinkManTel(params.getLinkManTel());
        entity.setState(params.getState());
        entity.setApplyDate(LocalDateTime.now());
        entity.setApplyUserId(userInfo.getId());
        entity.setApplyIp(userInfo.getIp());

        entity.setLlType(params.getLlType());
        entity.setLongitude(params.getLongitude());
        entity.setLatitude(params.getLatitude());
        entity.setAddr(params.getAddr());

        if(StringUtils.isEmpty(params.getOpenTime())) {
            entity.setOpenTime(LocalDateTime.now());
        }else {
            entity.setOpenTime(LocalDateTimeUtils.parse_yyyyMMddHHmmss(params.getOpenTime()));
        }
        if(StringUtils.isEmpty(params.getEndTime())) {
            entity.setEndTime(LocalDateTimeUtils.plusDay(LocalDateTime.now(), 30));
            entity.setUseDay(30);
        }else {
            entity.setEndTime(LocalDateTimeUtils.parse_yyyyMMddHHmmss(params.getEndTime()));
        }
        entity.setUseUserNum(params.getUseUserNum());

        entity.setTags(StrSplitUtils.list2string(params.getTags()));
        entity.setMemo(params.getMemo());
        entity.setDetail(params.getDetail());
        entity.setOrders(params.getOrders());

        entity.setExtendOne(params.getExtendOne());
        entity.setExtendTwo(params.getExtendTwo());
        entity.setExtendThree(params.getExtendThree());
        entity.setExtendFour(params.getExtendFour());
        entity.setExtendFive(params.getExtendFive());

        if(!CollectionUtils.isEmpty(params.getImages())){
            entity.setImages(JSON.toJSONString(params.getImages()));
        }

        if(TenantConstant.TenantState.CS_Open.getCode().equals(entity.getState())) {
            entity.setCheckDate(LocalDateTime.now());
            entity.setCheckUserId(userInfo.getId());
            entity.setCheckIp(userInfo.getIp());
            entity.setCheckRemark("自动开通");
        }
        entity.addCreateParam(userInfo);
        entity.addEditParam(userInfo);


        List<TenantApplicationInfo> opens=new ArrayList<TenantApplicationInfo>();
        if(!CollectionUtils.isEmpty(params.getOpenItems())) {
            params.getOpenItems().forEach(item->{
                TenantApplicationInfo model=new TenantApplicationInfo();
                model.setTenantCode(entity.getTenantCode());
                model.setApplicationNo(item.getApplicationNo());
                model.setApplicationName(item.getApplicationName());
                model.setApplicationSysConfig(item.getApplicationSysConfig());
                model.setApplicationCustConfig(item.getApplicationCustConfig());
                model.addCreateParam(userInfo);
                model.addEditParam(userInfo);
                opens.add(model);
            });
        }
        return 	Dict.create().set("Company", entity).set("CompanyService", opens);
    }


    @Override
    public TenantFull save(TenantAddRequest params, LoginSimpleUserInfo userInfo) {
        ValidatorUtils.validate(params);
        Dict dict=this.getSaveMap(params, userInfo);
        TenantInfo entity=(TenantInfo)dict.getObj("Company");
        List<TenantApplicationInfo> opens=(List<TenantApplicationInfo>)dict.getObj("CompanyService");
        tenantInfoService.save(entity);
        if(opens.size()>0) {
            tenantApplicationInfoService.saveBatch(opens);
        }
        return TenantConvertUtils.getTenantFull(entity);
    }

    @Override
    public TenantFull save2user(Tenant2UserAddRequest params, LoginSimpleUserInfo userInfo) {
        ValidatorUtils.validate(params);
        ValidateUserRequest validateUserRequest=new ValidateUserRequest();
        validateUserRequest.setUserName(params.getUserName());
        BaseClientResult<ValidateUserResponse>  validateUserResponse= userRegisterRemoteService.validateUserName(validateUserRequest);
        //todo:错误判断
        if(!BaseReturnEnum.SUCCESS.getCode().equals(validateUserResponse.getCode())){
            throw new BusinessException(validateUserResponse.getCode(), validateUserResponse.getMsg());
        }
        if(null == validateUserResponse.getData()){
            throw new BusinessException(BaseReturnEnum.SYSTEM_ERROR);
        }
        if(BaseConstant.YNEnum.YES.getCode().equals(validateUserResponse.getData().getFlag())){
            throw new BusinessException(BaseReturnEnum.DATA_EXISTS,"用户名已存在");
        }

        int companyNum= tenantInfoService.count(new QueryWrapper<TenantInfo>()
                .eq("name",params.getName())
        );
        if(companyNum>0){
            throw new BusinessException(ErrorTenantEnum.Company_Name_Exist);
        }

        Dict dict=this.getSaveMap(params, userInfo);
        TenantInfo entity=(TenantInfo)dict.getObj("Company");
        List<TenantApplicationInfo> opens=(List<TenantApplicationInfo>)dict.getObj("CompanyService");

        RegisterEmployeeRequest registerParam=new RegisterEmployeeRequest();
        registerParam.setCompanyNo(entity.getTenantCode());
        registerParam.setRoles(params.getRoles());
        registerParam.setUserTypeOne("1"); //员工
        registerParam.setUserName(params.getUserName());
        registerParam.setPassword(params.getPassword());
        registerParam.setNationCode(params.getNationCode());
        registerParam.setMobile(params.getMobile());
        registerParam.setEmail(params.getEmail());
        registerParam.setNickName(entity.getName());
        registerParam.setSourceOne("1"); //自助注册
        registerParam.setRegIp(userInfo.getIp());
//		registerParam.setRegWay();
        BaseClientResult<UserFull> user=userRegisterRemoteService.register(registerParam);
        if (BaseReturnEnum.SUCCESS.getCode().equals(user.getCode())) {
            entity.setAdminUserId(user.getData().getId());
        }
        tenantInfoService.save(entity);
        if(opens.size()>0) {
            tenantApplicationInfoService.saveBatch(opens);
        }
        return TenantConvertUtils.getTenantFull(entity);
    }

    @Override
    public TenantFull check(TenantCheckRequest params, LoginSimpleUserInfo userInfo) {
        ValidatorUtils.validate(params);
        TenantInfo entity= tenantInfoService.getById(params.getCompanyNo());
        if (entity == null || BaseConstant.EnabledEnum.DISABLED.getCode().equals(entity.getRowsState())) {
            throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
        }
        if(!TenantConstant.TenantState.CS_Ing.getCode().equals(entity.getState())){
            return TenantConvertUtils.getTenantFull(entity);
        }
        entity.setUseDay(params.getUseDay());
        entity.setState(params.getState());
        if(StringUtils.isEmpty(params.getOpenTime())) {
            entity.setOpenTime(LocalDateTime.now());
        }else {
            entity.setOpenTime(LocalDateTimeUtils.parse_yyyyMMddHHmmss(params.getOpenTime()));
        }
        entity.setEndTime(LocalDateTimeUtils.plusDay(entity.getOpenTime(), params.getUseDay()));
        entity.setUseUserNum(params.getUseUserNum());
        entity.setCheckRemark(params.getCheckRemark());
        entity.setCheckDate(LocalDateTime.now());
        entity.setCheckIp(userInfo.getIp());
        entity.setCheckUserId(userInfo.getId());
        entity.addEditParam(userInfo);
        tenantInfoService.updateById(entity);

        List<TenantApplicationInfo> opens=new ArrayList<TenantApplicationInfo>();
        if(!CollectionUtils.isEmpty(params.getOpenItems())) {
            params.getOpenItems().forEach(item->{
                TenantApplicationInfo model=new TenantApplicationInfo();
                model.setTenantCode(entity.getTenantCode());
                model.setApplicationNo(item.getApplicationNo());
                model.setApplicationName(item.getApplicationName());
                model.setApplicationSysConfig(item.getApplicationSysConfig());
                model.setApplicationCustConfig(item.getApplicationCustConfig());
                model.addCreateParam(userInfo);
                model.addEditParam(userInfo);
                opens.add(model);
            });
        }

        if(opens.size()>0){
            tenantApplicationInfoService.saveBatch(opens);
        }
        return TenantConvertUtils.getTenantFull(entity);
    }

    @Transactional
    @Override
    public TenantFull update(TenantUpdateRequest params, LoginSimpleUserInfo userInfo) {
        ValidatorUtils.validate(params);
        TenantInfo entity= tenantInfoService.getById(params.getTenantCode());
        if (entity == null || BaseConstant.EnabledEnum.DISABLED.getCode().equals(entity.getRowsState())) {
            throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
        }
        entity.setName(params.getName());
        entity.setShortName(params.getShortName());
        entity.setType(params.getType());
        entity.setLogo(params.getLogo());
        entity.setSourceType(params.getSourceType());
        entity.setSource(params.getSource());
        entity.setLinkManName(params.getLinkManName());
        entity.setLinkManMobile(params.getLinkManMobile());
        entity.setLinkManTel(params.getLinkManTel());
        entity.setEndTime(LocalDateTimeUtils.parse_yyyyMMddHHmmss(params.getEndTime()));
        entity.setUseUserNum(params.getUseUserNum());
        entity.setLlType(params.getLlType());
        entity.setLongitude(params.getLongitude());
        entity.setLatitude(params.getLatitude());
        entity.setAddr(params.getAddr());
        entity.setTags(StrSplitUtils.list2string(params.getTags()));
        entity.setMemo(params.getMemo());
        entity.setDetail(params.getDetail());
        entity.setOrders(params.getOrders());
        entity.setExtendOne(params.getExtendOne());
        entity.setExtendTwo(params.getExtendTwo());
        entity.setExtendThree(params.getExtendThree());
        entity.setExtendFour(params.getExtendFour());
        entity.addEditParam(userInfo);
        tenantInfoService.updateById(entity);
        List<TenantApplicationInfo> opens=new ArrayList<TenantApplicationInfo>();
        if(!CollectionUtils.isEmpty(params.getOpenItems())) {
            tenantApplicationInfoService.remove(
                    new QueryWrapper<TenantApplicationInfo>()
                            .eq("tenant_code", entity.getTenantCode()));
            params.getOpenItems().forEach(item->{
                TenantApplicationInfo model=new TenantApplicationInfo();
                model.setTenantCode(entity.getTenantCode());
                model.setApplicationNo(item.getApplicationNo());
                model.setApplicationName(item.getApplicationName());
                model.setApplicationSysConfig(item.getApplicationSysConfig());
                model.setApplicationCustConfig(item.getApplicationCustConfig());
                model.addCreateParam(userInfo);
                model.addEditParam(userInfo);
                opens.add(model);
            });
        }
        if(opens.size()>0) {
            tenantApplicationInfoService.saveBatch(opens);
        }
        return TenantConvertUtils.getTenantFull(entity);
    }

    @Override
    public TenantFull frozen(String tenantCode, LoginSimpleUserInfo userInfo) {
        TenantInfo entity=tenantInfoService.getById(tenantCode);
        if (entity == null || BaseConstant.EnabledEnum.DISABLED.getCode().equals(entity.getRowsState())) {
            throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
        }
        if (TenantConstant.TenantState.CS_Open.getCode().equals(entity.getState())){
            entity.setState(TenantConstant.TenantState.CS_Frozen.getCode());
            entity.addEditParam(userInfo);
            tenantInfoService.updateById(entity);
        }
        return TenantConvertUtils.getTenantFull(entity);
    }

    @Override
    public TenantFull unfreeze(String tenantCode, LoginSimpleUserInfo userInfo) {
        TenantInfo entity=tenantInfoService.getById(tenantCode);
        if (entity == null || BaseConstant.EnabledEnum.DISABLED.getCode().equals(entity.getRowsState())) {
            throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
        }
        if (TenantConstant.TenantState.CS_Frozen.getCode().equals(entity.getState())){
            entity.setState(TenantConstant.TenantState.CS_Open.getCode());
            entity.addEditParam(userInfo);
            tenantInfoService.updateById(entity);
        }
        return TenantConvertUtils.getTenantFull(entity);
    }

    @Override
    public TenantFull del(String tenantCode, LoginSimpleUserInfo userInfo) {
        TenantInfo entity=tenantInfoService.getById(tenantCode);
        if (entity == null || BaseConstant.EnabledEnum.DISABLED.getCode().equals(entity.getRowsState())) {
            throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
        }
        entity.setRowsState(BaseConstant.EnabledEnum.DISABLED.getCode());
        entity.addEditParam(userInfo);
        tenantInfoService.updateById(entity);
        return TenantConvertUtils.getTenantFull(entity);
    }


}
